import numpy as np
import pandas as pd
from typing import Dict, List, Any, Optional, Tuple
import logging
from datetime import datetime, timedelta
from collections import defaultdict
import json

logger = logging.getLogger(__name__)

class LearningAnalyzer:
    """学习分析器，用于分析学生的学习行为和进度"""
    
    def __init__(self):
        self.config = {
            'progress_weight': 0.4,
            'performance_weight': 0.3,
            'engagement_weight': 0.3,
            'time_decay_factor': 0.95,  # 时间衰减因子
            'min_study_time': 5.0,  # 最小有效学习时间（分钟）
            'max_study_time': 180.0  # 最大有效学习时间（分钟）
        }
    
    def analyze_learning_progress(self, student_id: int, 
                                learning_records: List[Dict[str, Any]],
                                course_info: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        分析学习进度
        
        Args:
            student_id: 学生ID
            learning_records: 学习记录列表
            course_info: 课程信息
            
        Returns:
            学习进度分析结果
        """
        try:
            if not learning_records:
                return self._get_empty_analysis(student_id)
            
            # 基础统计
            basic_stats = self._calculate_basic_statistics(learning_records)
            
            # 进度分析
            progress_analysis = self._analyze_progress(learning_records, course_info)
            
            # 学习行为分析
            behavior_analysis = self._analyze_learning_behavior(learning_records)
            
            # 时间模式分析
            time_analysis = self._analyze_time_patterns(learning_records)
            
            # 成绩分析
            performance_analysis = self._analyze_performance(learning_records)
            
            # 综合评估
            overall_assessment = self._calculate_overall_assessment(
                progress_analysis, behavior_analysis, performance_analysis
            )
            
            return {
                "student_id": student_id,
                "basic_statistics": basic_stats,
                "progress_analysis": progress_analysis,
                "behavior_analysis": behavior_analysis,
                "time_analysis": time_analysis,
                "performance_analysis": performance_analysis,
                "overall_assessment": overall_assessment,
                "recommendations": self._generate_recommendations(
                    progress_analysis, behavior_analysis, performance_analysis
                )
            }
            
        except Exception as e:
            logger.error(f"学习进度分析失败: {str(e)}")
            return {"error": str(e)}
    
    def _get_empty_analysis(self, student_id: int) -> Dict[str, Any]:
        """获取空分析结果"""
        return {
            "student_id": student_id,
            "basic_statistics": {
                "total_study_time": 0,
                "total_sessions": 0,
                "avg_session_duration": 0,
                "completion_rate": 0
            },
            "progress_analysis": {
                "overall_progress": 0,
                "progress_trend": "stable",
                "strength_areas": [],
                "weakness_areas": []
            },
            "behavior_analysis": {
                "study_consistency": 0,
                "engagement_level": "low",
                "learning_efficiency": 0
            },
            "time_analysis": {
                "preferred_time": "unknown",
                "study_frequency": 0,
                "time_distribution": {}
            },
            "performance_analysis": {
                "average_score": 0,
                "score_trend": "stable",
                "improvement_rate": 0
            },
            "overall_assessment": {
                "overall_score": 0,
                "level": "beginner",
                "status": "inactive"
            },
            "recommendations": ["开始学习以获取个性化建议"]
        }
    
    def _calculate_basic_statistics(self, learning_records: List[Dict[str, Any]]) -> Dict[str, Any]:
        """计算基础统计信息"""
        if not learning_records:
            return {}
        
        # 学习时间统计
        study_times = [record.get('study_time', 0) for record in learning_records]
        total_study_time = sum(study_times)
        avg_study_time = np.mean(study_times) if study_times else 0
        
        # 完成率统计
        completion_rates = [record.get('completion_rate', 0) for record in learning_records]
        avg_completion_rate = np.mean(completion_rates) if completion_rates else 0
        
        # 交互次数统计
        interaction_counts = [record.get('interaction_count', 0) for record in learning_records]
        total_interactions = sum(interaction_counts)
        avg_interactions = np.mean(interaction_counts) if interaction_counts else 0
        
        # 学习会话统计
        session_dates = set()
        for record in learning_records:
            if 'created_time' in record:
                date = record['created_time'].date() if isinstance(record['created_time'], datetime) else record['created_time']
                session_dates.add(date)
        
        return {
            "total_study_time": total_study_time,
            "total_sessions": len(session_dates),
            "avg_session_duration": avg_study_time,
            "completion_rate": avg_completion_rate,
            "total_interactions": total_interactions,
            "avg_interactions_per_session": avg_interactions,
            "study_days": len(session_dates),
            "first_study_date": min(session_dates) if session_dates else None,
            "last_study_date": max(session_dates) if session_dates else None
        }
    
    def _analyze_progress(self, learning_records: List[Dict[str, Any]], 
                         course_info: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """分析学习进度"""
        if not learning_records:
            return {"overall_progress": 0, "progress_trend": "stable"}
        
        # 按时间排序
        sorted_records = sorted(learning_records, key=lambda x: x.get('created_time', datetime.now()))
        
        # 计算累计进度
        cumulative_progress = []
        current_progress = 0
        
        for record in sorted_records:
            completion_rate = record.get('completion_rate', 0)
            current_progress += completion_rate * 0.1  # 每次学习增加进度
            cumulative_progress.append(current_progress)
        
        # 计算总体进度
        overall_progress = min(100.0, current_progress)
        
        # 分析进度趋势
        if len(cumulative_progress) >= 3:
            recent_trend = np.polyfit(range(len(cumulative_progress[-3:])), cumulative_progress[-3:], 1)[0]
            if recent_trend > 0.1:
                progress_trend = "improving"
            elif recent_trend < -0.1:
                progress_trend = "declining"
            else:
                progress_trend = "stable"
        else:
            progress_trend = "stable"
        
        # 识别强项和弱项
        strength_areas, weakness_areas = self._identify_strength_weakness(learning_records)
        
        return {
            "overall_progress": overall_progress,
            "progress_trend": progress_trend,
            "strength_areas": strength_areas,
            "weakness_areas": weakness_areas,
            "progress_history": cumulative_progress
        }
    
    def _analyze_learning_behavior(self, learning_records: List[Dict[str, Any]]) -> Dict[str, Any]:
        """分析学习行为"""
        if not learning_records:
            return {"study_consistency": 0, "engagement_level": "low", "learning_efficiency": 0}
        
        # 学习一致性分析
        study_consistency = self._calculate_study_consistency(learning_records)
        
        # 参与度分析
        engagement_level = self._calculate_engagement_level(learning_records)
        
        # 学习效率分析
        learning_efficiency = self._calculate_learning_efficiency(learning_records)
        
        # 学习模式分析
        learning_patterns = self._analyze_learning_patterns(learning_records)
        
        return {
            "study_consistency": study_consistency,
            "engagement_level": engagement_level,
            "learning_efficiency": learning_efficiency,
            "learning_patterns": learning_patterns
        }
    
    def _analyze_time_patterns(self, learning_records: List[Dict[str, Any]]) -> Dict[str, Any]:
        """分析时间模式"""
        if not learning_records:
            return {"preferred_time": "unknown", "study_frequency": 0}
        
        # 按小时统计学习时间
        hourly_distribution = defaultdict(float)
        daily_distribution = defaultdict(int)
        
        for record in learning_records:
            if 'created_time' in record:
                study_time = record.get('study_time', 0)
                created_time = record['created_time']
                
                if isinstance(created_time, str):
                    try:
                        created_time = datetime.fromisoformat(created_time.replace('Z', '+00:00'))
                    except:
                        continue
                
                hour = created_time.hour
                day = created_time.strftime('%A')
                
                hourly_distribution[hour] += study_time
                daily_distribution[day] += 1
        
        # 找出最佳学习时间
        if hourly_distribution:
            preferred_hour = max(hourly_distribution.items(), key=lambda x: x[1])[0]
            preferred_time = f"{preferred_hour:02d}:00"
        else:
            preferred_time = "unknown"
        
        # 计算学习频率
        total_days = len(set(record.get('created_time', datetime.now()).date() 
                           for record in learning_records if 'created_time' in record))
        study_frequency = total_days / 30 if total_days > 0 else 0  # 每月学习天数
        
        return {
            "preferred_time": preferred_time,
            "study_frequency": study_frequency,
            "hourly_distribution": dict(hourly_distribution),
            "daily_distribution": dict(daily_distribution)
        }
    
    def _analyze_performance(self, learning_records: List[Dict[str, Any]]) -> Dict[str, Any]:
        """分析学习成绩"""
        if not learning_records:
            return {"average_score": 0, "score_trend": "stable", "improvement_rate": 0}
        
        # 提取成绩数据
        scores = []
        for record in learning_records:
            if 'score' in record and record['score'] is not None:
                scores.append(record['score'])
        
        if not scores:
            return {"average_score": 0, "score_trend": "stable", "improvement_rate": 0}
        
        # 计算平均分
        average_score = np.mean(scores)
        
        # 分析成绩趋势
        if len(scores) >= 3:
            recent_scores = scores[-3:]
            score_trend = np.polyfit(range(len(recent_scores)), recent_scores, 1)[0]
            
            if score_trend > 1:
                trend = "improving"
            elif score_trend < -1:
                trend = "declining"
            else:
                trend = "stable"
        else:
            trend = "stable"
        
        # 计算改进率
        if len(scores) >= 2:
            improvement_rate = (scores[-1] - scores[0]) / len(scores)
        else:
            improvement_rate = 0
        
        return {
            "average_score": average_score,
            "score_trend": trend,
            "improvement_rate": improvement_rate,
            "score_history": scores,
            "best_score": max(scores),
            "recent_score": scores[-1] if scores else 0
        }
    
    def _calculate_overall_assessment(self, progress_analysis: Dict[str, Any],
                                    behavior_analysis: Dict[str, Any],
                                    performance_analysis: Dict[str, Any]) -> Dict[str, Any]:
        """计算综合评估"""
        # 进度分数
        progress_score = progress_analysis.get('overall_progress', 0) / 100.0
        
        # 行为分数
        behavior_score = behavior_analysis.get('learning_efficiency', 0) / 10.0
        
        # 成绩分数
        performance_score = performance_analysis.get('average_score', 0) / 100.0
        
        # 综合分数
        overall_score = (
            progress_score * self.config['progress_weight'] +
            behavior_score * self.config['engagement_weight'] +
            performance_score * self.config['performance_weight']
        ) * 100
        
        # 确定学习水平
        if overall_score >= 80:
            level = "advanced"
        elif overall_score >= 60:
            level = "intermediate"
        else:
            level = "beginner"
        
        # 确定学习状态
        if behavior_analysis.get('study_consistency', 0) > 0.7:
            status = "active"
        elif behavior_analysis.get('study_consistency', 0) > 0.3:
            status = "moderate"
        else:
            status = "inactive"
        
        return {
            "overall_score": overall_score,
            "level": level,
            "status": status,
            "component_scores": {
                "progress": progress_score * 100,
                "behavior": behavior_score * 100,
                "performance": performance_score * 100
            }
        }
    
    def _calculate_study_consistency(self, learning_records: List[Dict[str, Any]]) -> float:
        """计算学习一致性"""
        if not learning_records:
            return 0.0
        
        # 按日期分组学习记录
        daily_records = defaultdict(list)
        for record in learning_records:
            if 'created_time' in record:
                date = record['created_time'].date() if isinstance(record['created_time'], datetime) else record['created_time']
                daily_records[date].append(record)
        
        # 计算学习天数的连续性
        dates = sorted(daily_records.keys())
        if len(dates) < 2:
            return 0.5
        
        consecutive_days = 0
        max_consecutive = 0
        current_consecutive = 1
        
        for i in range(1, len(dates)):
            if (dates[i] - dates[i-1]).days == 1:
                current_consecutive += 1
            else:
                max_consecutive = max(max_consecutive, current_consecutive)
                current_consecutive = 1
        
        max_consecutive = max(max_consecutive, current_consecutive)
        
        # 一致性分数
        consistency = min(1.0, max_consecutive / len(dates))
        return consistency
    
    def _calculate_engagement_level(self, learning_records: List[Dict[str, Any]]) -> str:
        """计算参与度水平"""
        if not learning_records:
            return "low"
        
        # 计算平均交互次数
        interaction_counts = [record.get('interaction_count', 0) for record in learning_records]
        avg_interactions = np.mean(interaction_counts) if interaction_counts else 0
        
        # 计算平均学习时间
        study_times = [record.get('study_time', 0) for record in learning_records]
        avg_study_time = np.mean(study_times) if study_times else 0
        
        # 计算完成率
        completion_rates = [record.get('completion_rate', 0) for record in learning_records]
        avg_completion = np.mean(completion_rates) if completion_rates else 0
        
        # 综合评估
        engagement_score = (
            min(avg_interactions / 10.0, 1.0) * 0.4 +
            min(avg_study_time / 60.0, 1.0) * 0.3 +
            avg_completion / 100.0 * 0.3
        )
        
        if engagement_score >= 0.7:
            return "high"
        elif engagement_score >= 0.4:
            return "moderate"
        else:
            return "low"
    
    def _calculate_learning_efficiency(self, learning_records: List[Dict[str, Any]]) -> float:
        """计算学习效率"""
        if not learning_records:
            return 0.0
        
        # 计算单位时间的完成率
        efficiency_scores = []
        for record in learning_records:
            study_time = record.get('study_time', 0)
            completion_rate = record.get('completion_rate', 0)
            
            if study_time > 0:
                efficiency = completion_rate / study_time
                efficiency_scores.append(efficiency)
        
        if not efficiency_scores:
            return 0.0
        
        # 返回平均效率
        avg_efficiency = np.mean(efficiency_scores)
        return min(10.0, avg_efficiency * 10)  # 标准化到0-10
    
    def _analyze_learning_patterns(self, learning_records: List[Dict[str, Any]]) -> Dict[str, Any]:
        """分析学习模式"""
        if not learning_records:
            return {}
        
        # 学习时长模式
        study_times = [record.get('study_time', 0) for record in learning_records]
        short_sessions = sum(1 for t in study_times if t < 30)
        medium_sessions = sum(1 for t in study_times if 30 <= t < 60)
        long_sessions = sum(1 for t in study_times if t >= 60)
        
        # 学习频率模式
        session_dates = set()
        for record in learning_records:
            if 'created_time' in record:
                date = record['created_time'].date() if isinstance(record['created_time'], datetime) else record['created_time']
                session_dates.add(date)
        
        return {
            "session_length_pattern": {
                "short_sessions": short_sessions,
                "medium_sessions": medium_sessions,
                "long_sessions": long_sessions
            },
            "total_study_days": len(session_dates),
            "avg_sessions_per_day": len(learning_records) / len(session_dates) if session_dates else 0
        }
    
    def _identify_strength_weakness(self, learning_records: List[Dict[str, Any]]) -> Tuple[List[str], List[str]]:
        """识别强项和弱项"""
        # 按资源类型分组
        resource_performance = defaultdict(list)
        
        for record in learning_records:
            resource_type = record.get('resource_type', 'unknown')
            completion_rate = record.get('completion_rate', 0)
            resource_performance[resource_type].append(completion_rate)
        
        # 计算每种类型的平均表现
        type_averages = {}
        for resource_type, rates in resource_performance.items():
            type_averages[resource_type] = np.mean(rates)
        
        # 识别强项和弱项
        if not type_averages:
            return [], []
        
        avg_performance = np.mean(list(type_averages.values()))
        strength_areas = [rtype for rtype, avg in type_averages.items() if avg > avg_performance * 1.1]
        weakness_areas = [rtype for rtype, avg in type_averages.items() if avg < avg_performance * 0.9]
        
        return strength_areas, weakness_areas
    
    def _generate_recommendations(self, progress_analysis: Dict[str, Any],
                                behavior_analysis: Dict[str, Any],
                                performance_analysis: Dict[str, Any]) -> List[str]:
        """生成学习建议"""
        recommendations = []
        
        # 基于进度的建议
        progress = progress_analysis.get('overall_progress', 0)
        if progress < 30:
            recommendations.append("建议增加学习时间，制定详细的学习计划")
        elif progress < 60:
            recommendations.append("学习进度良好，建议保持当前学习节奏")
        else:
            recommendations.append("学习进度优秀，可以尝试更具挑战性的内容")
        
        # 基于行为的建议
        consistency = behavior_analysis.get('study_consistency', 0)
        if consistency < 0.5:
            recommendations.append("建议建立规律的学习习惯，保持学习的连续性")
        
        engagement = behavior_analysis.get('engagement_level', 'low')
        if engagement == 'low':
            recommendations.append("建议增加学习互动，提高学习参与度")
        
        # 基于成绩的建议
        performance = performance_analysis.get('average_score', 0)
        if performance < 60:
            recommendations.append("建议复习基础知识，巩固薄弱环节")
        elif performance < 80:
            recommendations.append("成绩良好，建议多做练习提高应用能力")
        else:
            recommendations.append("成绩优秀，可以尝试更高难度的挑战")
        
        # 基于弱项的建议
        weakness_areas = progress_analysis.get('weakness_areas', [])
        if weakness_areas:
            recommendations.append(f"建议重点加强以下领域的学习：{', '.join(weakness_areas)}")
        
        return recommendations[:5]  # 最多返回5条建议